#include "QRONode_P.h"

struct SignalParamPacket
{
    bool isEncode;//参数是否经过了网络化编码
    QVariantList param;
};

static QVariantList signalParamConvert(QRONode::Private* _P,QMetaMethod method,const SignalParamPacket& paramPacket,bool isToNet);

void QRONode::Private::onActiveMethod(QObject *obj, int method, QVariantList param,QRemoteObject2::InvokeCallBack callBack)
{
    bool success = false;
    QString message;
    do
    {
        auto meta = obj->metaObject();
        const auto m = QRemoteObject2Meta::Instance()->findMethodData(meta->className(),method);
        if(m.index == -1) return;

        auto flag = m.behaiovr;
        if(flag == QRemoteObject2::ROSignalBehavior::None) {
            message = QStringLiteral("目标类型未注册");
            break;
        };

        InvokeID invokeId = 0;

        if(callBack)
        {
            if(flag != QRemoteObject2::ROSignalBehavior::ServerOnly && flag != QRemoteObject2::ROSignalBehavior::OwnerOnly)
            {
                message = QStringLiteral("带有回调的远程调用仅能对单播类型的函数使用 如ServerOnly和OwnerOnly");
                break;
            }

            //将此次调用结果放入队列
            invokeId = allocInvokeID();
            callBackQueue[invokeId] = callBack;
        }

        //不管信号是在哪里执行的，客户端都会把此次行为提交到服务端 由服务端裁决
        auto localId = m_objectIdMap[obj];
        //本地id映射为远端id
        auto remoteId = m_remoteIdMapper.key(localId);

        if(QRemoteObject2::ROSignalBehavior::OwnerOnly == flag)
        {//向服务器发起请求之前先看看这个对象是否属于自己，不属于自己就直接过滤。
            if(notBelongTo(localId))
            {
                message = QStringLiteral("该对象不属于本客户端，无法调用OwnerOnly函数");
                break;
            }
        }

        auto metaMethod = meta->method(method);

        //将信号参数编码
        param = signalParamConvert(this,metaMethod,{false,param},true);
        //向服务器发起调用请求
        m_channel->serverCall(remoteId,method,param,invokeId);
        success = true;
    }
    while(false);

    if(!success)
    {
        if(callBack)
        {
            callBack({},false,message);
        }
    }
}

void QRONode::Private::onClientCall(int id, int method, QVariantList param,int sync,bool isSource)
{
    auto localId = m_remoteIdMapper[id];

    const auto& data = m_objectDataMap[localId];

    auto meta = data->obj->metaObject();
    auto metamethod = meta->method(method);

    param = signalParamConvert(this,metamethod,{true,param},false);
    auto ret = invokeMetaMethod(data->obj,metamethod,param);

    if(sync)//同步码非空 代表这是一次同步调用
    {
        if(isSource)
        {
            //此次的调用是由本端自己发起的
            auto callBack = callBackQueue.value(sync);
            if(callBack)
            {
                callBack(ret,true,"");
            }
            callBackQueue.remove(sync);
        }
        else{
            //此次调用是由服务端发起的，通知服务端调用完毕
            m_channel->clientCallFinished(sync,ret,true);
        }
    }
}

void QRONode::Private::onServerCallFinished(int sync,QVariant res,bool success){
    if(callBackQueue.contains(sync))
    {
        callBackQueue[sync](res,success,"");
        callBackQueue.remove(sync);
    }
}

static QVariantList signalParamConvert(QRONode::Private* _P,QMetaMethod method,const SignalParamPacket& paramPacket,bool isToNet)
{
    auto ret = paramPacket.param;

    if(paramPacket.isEncode && !isToNet)
    {
        auto paramCount = method.parameterCount();
        for(int i = 0;i<paramCount;i++)
        {
            auto targetType = method.parameterType(i);
            _P->valueFromNet(ret[i],targetType);
        }
    }
    else{
        for(auto &i:ret)
        {
            _P->valueToNet(i);
        }
    }
    return ret;
}
